#include "handle.h"
#include <cstdlib>
#include <cstring>
#include <ctime>

SNAKE_handle::SNAKE_handle( char Snake_field [] [SNAKE_VERTICAL] ):
  last_direction ( SNAKE_RIGHT )
{
    //set all elements of the Snake field to ' '
	memset ( this->snake_body, ' ', SNAKE_MAX_SNAKE_LENGTH );
    //check the insance. 
    //important for later version
	this->instanceCount++;
}

int SNAKE_handle::is_Snake ( int x, int y, char Snake_field[][SNAKE_VERTICAL] )const
{
  if ( Snake_field [x] [y] == 'X' || Snake_field [x] [y] == '#' )
    return SNAKE_BODY;
  else if ( Snake_field [x] [y] == 'O' )
    return SNAKE_FOOD;
  return SNAKE_FIELD_ELEMENT;
}

void SNAKE_handle::set_snake ( char Snake_field[][SNAKE_VERTICAL] )
{
	//Set the snake in the middle of the field
	Snake_field [SNAKE_HORIZONTAL/2]	[SNAKE_VERTICAL/2 + 1]	= 'X';
	Snake_field [SNAKE_HORIZONTAL/2]	[SNAKE_VERTICAL/2]		= '#';
	Snake_field [SNAKE_HORIZONTAL/2]	[SNAKE_VERTICAL/2 - 1]	= '#';
	Snake_field [SNAKE_HORIZONTAL/2]	[SNAKE_VERTICAL/2 - 2]	= '#';
	/*
	* load the adress of the Snake-body in a array.
	* This array has saved the body elements in the right order.
	*/
	this->snake_body[0] = &Snake_field [SNAKE_HORIZONTAL/2]	[SNAKE_VERTICAL/2 + 1];
	this->snake_body[1] = &Snake_field [SNAKE_HORIZONTAL/2]	[SNAKE_VERTICAL/2];
	this->snake_body[2] = &Snake_field [SNAKE_HORIZONTAL/2]	[SNAKE_VERTICAL/2 - 1];
	this->snake_body[3] = &Snake_field [SNAKE_HORIZONTAL/2]	[SNAKE_VERTICAL/2 - 2];
    //first bodysize is 4. The counter is increment when a food is fooden
	this->body_elements = 4;
  
	this->set_food ( Snake_field );

	//position of the head
	this->head.hight = SNAKE_HORIZONTAL/2;
	this->head.wide = SNAKE_VERTICAL/2 + 1;
}

bool SNAKE_handle::snake_move ( char Snake_field[][SNAKE_VERTICAL] )
{
	int body = this->body_elements;
	bool feeding_check = false;
	if ( this->feeding ( Snake_field ) )
	{
	  feeding_check = true;
		*this->snake_body	[body-1] = ' ';
	}
	else 
	{
		body++;
	}
	while ( body-1 )
	{
		Snake_field	[this->head.hight]	[this->head.wide] = '#';
		this->snake_body	[body-1] = this->snake_body	[body-2];
		body--;
	}
	switch ( this->last_direction )
	{
		case SNAKE_RIGHT: 
		{
			if ( this->head.wide+1 >= SNAKE_VERTICAL )
			{
				this->head.wide = 0;
			}
			else
			{
				this->head.wide++;
			}
			Snake_field	[this->head.hight]	[this->head.wide] = 'X';
			break;
		}
		case SNAKE_HIGH:
		{
			if ( !this->head.hight )
			{
				this->head.hight = SNAKE_HORIZONTAL-1;
			}
			else
			{
				this->head.hight--;
			}
			Snake_field	[this->head.hight]	[this->head.wide] = 'X';
			break;
		}
		case SNAKE_DOWN:
		{
			if ( this->head.hight + 1 >= SNAKE_HORIZONTAL )
			{
				this->head.hight = 0;
			}
			else
			{
				this->head.hight++;
			}
			Snake_field	[this->head.hight]	[this->head.wide] = 'X';
			break;
		}
		case SNAKE_LEFT:
		{
			if ( !this->head.wide )
			{
				this->head.wide = SNAKE_VERTICAL-1;
			}
			else
			{
				this->head.wide--;
			}
			Snake_field	[this->head.hight]	[this->head.wide] = 'X';
			break;
		}
	}
	this->snake_body [0] = &Snake_field	[this->head.hight]	[this->head.wide];
	return feeding_check;
}

bool SNAKE_handle::feeding( char Snake_field[][SNAKE_VERTICAL] )
{
	bool check_feeding = true;
	switch ( this->last_direction )
	{
		case SNAKE_RIGHT:
		{
			if ( &Snake_field	[this->head.hight]	[this->head.wide+1] == food && this->head.wide + 1 < SNAKE_VERTICAL )
			{
				if_fooding ( Snake_field );
				check_feeding = false;
			}
			else if ( &Snake_field [this->head.hight] [0] == food && this->head.wide == SNAKE_VERTICAL - 1)
			{
			  if_fooding  ( Snake_field );
			  check_feeding = false;
			}
			break;
		}
		case SNAKE_LEFT:
		{
			if ( &Snake_field [this->head.hight] [ this->head.wide-1 ] == this->food && this->head.wide )
			{
  			this->if_fooding ( Snake_field );
				check_feeding = false;
			}
			else if ( &Snake_field [this->head.hight] [SNAKE_VERTICAL-1] == this->food && this->head.wide == 0 )
			{
			  this->if_fooding ( Snake_field );
			  check_feeding = false;
			}
			break;
		}
		case SNAKE_DOWN:
		{
			if (  &Snake_field	[this->head.hight+1]	[this->head.wide] == this->food && this->head.hight + 1 < SNAKE_HORIZONTAL )
			{
				this->if_fooding ( Snake_field );
				check_feeding = false;
			}
			else if ( &Snake_field [0] [this->head.wide] == this->food && this->head.hight == SNAKE_HORIZONTAL - 1 )
			{
			  this->if_fooding ( Snake_field );
			  check_feeding = false;
			}
			break;
		}
		case SNAKE_HIGH:
		{ 
			if (  &Snake_field	[this->head.hight-1]	[this->head.wide] == this->food )
			{
				this->if_fooding ( Snake_field );
				check_feeding = false;
			}
			else if ( &Snake_field [SNAKE_HORIZONTAL-1] [this->head.wide] == this->food && this->head.hight == 0 )
			{
			  this->if_fooding ( Snake_field );
			  check_feeding = false;
			}
			break;
		}
	}
	return check_feeding;
}

void SNAKE_handle::set_food(char Snake_field[][SNAKE_VERTICAL])
{
	int body = this->body_elements;
	struct coordinates next_food = {0};
	srand( (unsigned int) time ( 0 ) );
	do
	{
		next_food.hight = rand() % SNAKE_HORIZONTAL;
		next_food.wide	= rand() % SNAKE_VERTICAL;
		this->food = &Snake_field	[next_food.hight]	[next_food.wide];
	}
	while ( this->check_food ( body, Snake_field, next_food ) );
	*this->food = 'O';
}

void SNAKE_handle::if_fooding(char Snake_field[][SNAKE_VERTICAL])
{
	this->body_elements++;
	this->snake_body	[ this->body_elements - 1 ] = this->food;
	*this->snake_body [ this->body_elements - 1 ] = '#';
	this->set_food ( Snake_field );
}

bool SNAKE_handle::check_food(int body, char Snake_field[][SNAKE_VERTICAL], struct coordinates next_food) const
{
	bool if_food_is_at_snake = false;
	while ( body )
	{
		if ( this->food	== this->snake_body	[--body] )
		{
			if_food_is_at_snake = true;
			break;
		}
	}
	if ( food == &Snake_field [this->head.hight] [this->head.wide] )
	{
	  if_food_is_at_snake = true;
	}
	return if_food_is_at_snake;
}

bool SNAKE_handle::self_eat(char Snake_field[][SNAKE_VERTICAL])
{
	bool eat_not_body = true;
	int body = this->body_elements;
	while ( body - 1 )
	{ 
		if ( &Snake_field	[this->head.hight]	[this->head.wide] == this->snake_body [body--] )
		{
			eat_not_body = false;
			break;
		}
	}
	return eat_not_body;
}

int SNAKE_handle::instanceCount = 0;